package client

import (
	"net"
	"reflect"
	"rpc_client_demo/tools"
)

type MyClient struct {
	conn net.Conn
}

func NewMyClient(conn net.Conn) *MyClient {
	return &MyClient{
		conn: conn,
	}
}

func (m *MyClient) CallRpc(rpcName string, fPtr interface{}) {
	fn := reflect.ValueOf(fPtr).Elem()
	f := func(args []reflect.Value) []reflect.Value {
		//入参
		inArgs := make([]interface{}, 0, len(args))
		for _, arg := range args {
			inArgs = append(inArgs, arg.Interface())
		}
		cliSession := tools.NewSession(m.conn)
		//构建数据
		pushData := tools.RPCData{
			Name: rpcName,
			Args: inArgs,
		}
		//编码
		encodeData, err := tools.Encode(pushData)
		if err != nil {
			panic(err)
		}
		err = cliSession.Write(encodeData)
		if err != nil {
			panic(err)
		}
		//从服务端读取数据
		respData, err := cliSession.Read()
		if err != nil {
			panic(err)
		}
		//解码
		decodeData, err := tools.Decode(respData)
		if err != nil {
			panic(err)
		}
		outArgs := make([]reflect.Value, 0, len(decodeData.Args))
		for i, arg := range decodeData.Args {
			if arg == nil {
				outArgs = append(outArgs, reflect.Zero(fn.Type().Out(i)))
				continue
			}
			outArgs = append(outArgs, reflect.ValueOf(arg))
		}
		return outArgs
	}

	v := reflect.MakeFunc(fn.Type(), f)
	fn.Set(v)
}
